use axum::{
    extract::{Extension, Path},
    Json,
};
use chrono::Utc;
use serde::{Deserialize, Serialize};

use sqlx::{MySql, Pool};

use crate::{jwt::Claims, res::Res, utils::check_admin};

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct CreateReservation {
    phone: String,
    name: Option<String>,
    address: Option<String>,
    datetime: Option<String>,
    number_of_people: Option<i32>,
}

pub async fn create_reservation(
    claims: Claims,
    body: Json<CreateReservation>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    log::debug!("{:#?}", body);

    // 添加厨师数据到数据库
    let id = match sqlx::query!(
        r#"insert into 
        reservations(
           user_id, phone, name,address, datetime, number_of_people
        ) 
        values(?,?,?,?,?,?)"#,
        user_id,
        &body.phone,
        &body.name,
        &body.address,
        &body.datetime,
        &body.number_of_people
    )
    .execute(&pool)
    .await
    {
        Ok(v) => {
            // 插入后的用户编号
            v.last_insert_id()
        }
        Err(e) => {
            log::error!("预约出错:{}", e);
            res.set_code(-2);
            res.set_msg("服务端出错，请联系管理");
            return res;
        }
    };

    res.set_data(id);
    res
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Reservation {
    id: i32,
    user_id: Option<i32>,
    phone: String,
    name: Option<String>,
    address: Option<String>,
    datetime: Option<String>,
    number_of_people: Option<i32>,
    status: Option<i8>,
    msg: Option<String>,
    created_at: Option<String>,
}

/// 预约列表
pub async fn get_reservations(
    claims: Claims,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<Vec<Reservation>> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    // 管理员才可以获取列表
    let is_admin = check_admin(user_id, &pool).await;

    if !is_admin {
        res.set_code(-10);
        res.set_msg("只有管理员可以获取列表");
        return res;
    }

    let rs = match sqlx::query!("SELECT * FROM reservations order by created_at desc")
        .fetch_all(&pool)
        .await
    {
        Ok(v) => v,
        Err(e) => {
            log::error!("获取预约列表出错:{}", e);
            res.set_code(-1);
            res.set_msg("获取预约列表出错");
            return res;
        }
    };

    let mut reservations = vec![];
    for v in rs {
        reservations.push(Reservation {
            id: v.id,
            user_id: v.user_id,
            phone: v.phone,
            name: v.name,
            address: v.address,
            datetime: match v.datetime {
                Some(v) => Some(v.to_string()),
                None => None,
            },
            number_of_people: v.number_of_people,
            status: v.status,
            msg: v.msg,
            created_at: match v.created_at {
                Some(v) => Some(v.to_string()),
                None => None,
            },
        });
    }

    res.set_data(reservations);

    res
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct EditReservation {
    status: Option<i8>,
    msg: Option<String>,
}

pub async fn edit_reservation(
    claims: Claims,
    Path(id): Path<i32>,
    rs: Json<EditReservation>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    // 管理员才可以编辑
    let is_admin = check_admin(user_id, &pool).await;
    if !is_admin {
        res.set_code(-10);
        res.set_msg("只有管理员可以编辑");
        return res;
    }

    let rows_affected = match sqlx::query!(
        r#"update reservations 
           set status=?, msg=?
           where id=?"#,
        &rs.status,
        &rs.msg,
        id,
    )
    .execute(&pool)
    .await
    {
        Ok(v) => {
            // 受影响的行数
            v.rows_affected()
        }
        Err(e) => {
            log::error!("编辑菜单出错:{}", e);
            res.set_code(-2);
            res.set_msg("服务端出错，请联系管理");
            return res;
        }
    };

    res.set_data(rows_affected);

    res
}



pub async fn delete_reservation(
    claims: Claims,
    Path(id): Path<i32>,
    Extension(pool): Extension<Pool<MySql>>,
) -> Res<u64> {
    let mut res = Res::default();

    // 从token中获取用户编号
    let user_id: i32 = claims.sub.parse().unwrap();

    let is_admin = check_admin(user_id, &pool).await;
    if !is_admin {
        res.set_code(-10);
        res.set_msg("只有管理员可以删除");
        return res;
    }

    log::debug!("id:{}", id);
    let rows_affected = match sqlx::query!("delete from reservations where id=?", id)
        .execute(&pool)
        .await
    {
        Ok(v) => v.rows_affected(),
        Err(e) => {
            log::error!("删除预约出错:{}", e);
            res.set_code(-1);
            res.set_msg("删除预约出错");
            return res;
        }
    };
    res.set_data(rows_affected);
    res
}